/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the lkyh.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.lkyh.mes.codegen.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lkyh.mes.codegen.entity.*;
import com.lkyh.mes.codegen.mapper.GenTableInfoMapper;
import com.lkyh.mes.codegen.service.*;
import com.lkyh.mes.common.datasource.support.DynamicDataSourceContextHolder;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 表单管理
 *
 * @author lengleng
 * @date 2019-08-12 15:55:35
 */
@Service
@AllArgsConstructor
public class GenTableInfoServiceImpl extends ServiceImpl<GenTableInfoMapper, GenTableInfo> implements GenTableInfoService {

	private final GenColumnInfoService genColumnInfoService;
	private final GenPageInfoService genPageInfoService;
	private final GenVerifyInfoService genVerifyInfoService;
	private final GenFormActionService genFormActionService;
	private final GenIndexInfoService genIndexInfoService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean save(GenTableInfo genTableInfo) {
		if (super.save(genTableInfo)) {
			String s = FileUtil.readUtf8String("classpath:dbtemplate/table.js");
			List<GenColumnInfo> genColumnInfoList = JSONUtil.toList(JSONUtil.parseArray(s), GenColumnInfo.class);
			genColumnInfoList.forEach(i -> i.setTableId(genTableInfo.getId()));
			genColumnInfoService.saveBatch(genColumnInfoList);
		}
		return true;
	}

	@Override
	public boolean sync(Integer id) {
		GenTableInfo genTableInfo = this.getById(id);
		genTableInfo.setGenColumnInfoList(genColumnInfoService.list(Wrappers.query(new GenColumnInfo().setTableId(id))));
		genTableInfo.setGenIndexInfoList(genIndexInfoService.list(Wrappers.query(new GenIndexInfo().setTableId(id))));
		DynamicDataSourceContextHolder.setDataSourceType(genTableInfo.getDatasourceId());
		try {
			Integer tableExists = this.baseMapper.tableExists(genTableInfo.getDatabaseName(), genTableInfo.getName());
			if (tableExists > 0) {
				List<Map<String, String>> oldColumns = this.baseMapper.queryColumns(genTableInfo.getName());
				List<String> oldColumnNames = oldColumns.stream().map(m -> m.get("columnName")).collect(Collectors.toList());
				genTableInfo.getGenColumnInfoList().forEach(i -> {
					if (!CollUtil.contains(oldColumnNames, i.getName())) {
						i.setIsAdd(true);
					}
					i.setTableName(genTableInfo.getName());
					this.baseMapper.alterTable(i);
				});


				genTableInfo.getGenIndexInfoList().forEach(i -> {
					i.setTableName(genTableInfo.getName());
					this.baseMapper.alterTableIndex(i);
				});

			} else {
				this.baseMapper.createTable(genTableInfo);
			}
		} finally {
			DynamicDataSourceContextHolder.clearDataSourceType();
		}
		return true;
	}

	@Override
	public GenTableInfo getByIdWithChild(Integer id) {
		GenTableInfo genTableInfo = super.getById(id);
		this.buildChild(genTableInfo);
		return genTableInfo;
	}

	private void buildChild(GenTableInfo genTableInfo) {
		genTableInfo.setGenColumnInfoList(this.genColumnInfoService.list(Wrappers.query(new GenColumnInfo().setTableId(genTableInfo.getId()))));
		genTableInfo.setGenPageInfoList(this.genPageInfoService.list(Wrappers.lambdaQuery(new GenPageInfo().setTableId(genTableInfo.getId())).orderByAsc(GenPageInfo::getOrder)));
		genTableInfo.setGenVerifyInfoList(this.genVerifyInfoService.list(Wrappers.query(new GenVerifyInfo().setTableId(genTableInfo.getId()))));
		genTableInfo.setGenFormActionList(this.genFormActionService.list(Wrappers.query(new GenFormAction().setTableId(genTableInfo.getId()))));
		if (null != genTableInfo.getSubTable()) {
			genTableInfo.setGenSubTable(this.getByIdWithChild(genTableInfo.getSubTable()));
		}
	}

	@Override
	public List<GenTableInfo> listWithChild(Wrapper<GenTableInfo> queryWrapper) {
		List<GenTableInfo> list = super.list(queryWrapper);
		if (CollUtil.isNotEmpty(list)) {
			list.forEach(this::buildChild);
		}
		return list;
	}

	@Override
	public void dropTable(Integer id) {
		GenTableInfo genTableInfo = super.getById(id);
		super.removeById(id);
		genPageInfoService.remove(Wrappers.query(new GenPageInfo().setTableId(id)));
		genIndexInfoService.remove(Wrappers.query(new GenIndexInfo().setTableId(id)));
		genVerifyInfoService.remove(Wrappers.query(new GenVerifyInfo().setTableId(id)));
		genFormActionService.remove(Wrappers.query(new GenFormAction().setTableId(id)));
		DynamicDataSourceContextHolder.setDataSourceType(genTableInfo.getDatasourceId());
		try {
			this.baseMapper.dropTable(genTableInfo.getName());
		} catch (Exception e) {
			log.error("dropTable error", e);
		} finally {
			DynamicDataSourceContextHolder.clearDataSourceType();
		}
	}
}
